home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / arc / xadmasterdev.lha / xad / Sources / clients / HA.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-20  |  33.8 KB  |  1,309 lines

  1. #ifndef XADMASTER_HA_C
  2. #define XADMASTER_HA_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        HA.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: HA.c 1.3 (25.12.2001)
  9.     Author:        SDI
  10.     Distribution:    GPL
  11.     Description:    HA file archiver client
  12.  
  13.  1.0   05.11.00 : first version
  14.  1.1   23.12.00 : added missing TAG_DONE
  15.  1.2   03.10.01 : added special unix types
  16.  1.3   25.12.01 : added one more HSC break condition
  17. */
  18.  
  19. /* HA file archiver client for XAD.
  20.  * Copyright (C) 2000-2001 Dirk Stöcker <stoecker@epost.de>
  21.  *
  22.  * based on ha 0.999 by Harri Hirvola
  23.  * Copyright (C) 1993-1995 Harri Hirvola <harri.hirvola@vaisala.infonet.com>
  24.  *
  25.  * This program is free software; you can redistribute it and/or modify
  26.  * it under the terms of the GNU General Public License as published by
  27.  * the Free Software Foundation; either version 2 of the License, or
  28.  * (at your option) any later version.
  29.  * 
  30.  * This program is distributed in the hope that it will be useful,
  31.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  33.  * GNU General Public License for more details.
  34.  * 
  35.  * You should have received a copy of the GNU General Public License
  36.  * along with this program; if not, write to the Free Software
  37.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  38.  */
  39.  
  40. #define DEBUG
  41.  
  42. #include <proto/xadmaster.h>
  43. #include <exec/memory.h>
  44. #include "SDI_compiler.h"
  45. #include "ConvertE.c"
  46. #include "xadCPU.h"
  47. #include "xadIO.c"
  48. #define SDI_TO_ANSI
  49. #include "SDI_ASM_STD_protos.h"
  50.  
  51. #ifndef XADMASTERFILE
  52. #define HA_Client        FirstClient
  53. #define NEXTCLIENT        0
  54. #define XADMASTERVERSION    11
  55. UBYTE version[] = "$VER: HA 1.3 (25.12.2001)" CPUTEXT " GPL by Dirk Stöcker";
  56. #endif
  57. #define HA_VERSION        1
  58. #define HA_REVISION        3
  59.  
  60. #define HATYPE_CPY    0
  61. #define HATYPE_ASC    1
  62. #define HATYPE_HSC    2
  63. #define HATYPE_DIR    14
  64. #define HATYPE_SPECIAL    15
  65.  
  66. #define HAMTYPE_MSDOS    1
  67. #define HAMTYPE_UNIX    2
  68.  
  69. #define HA_ISVTX     0x0200
  70. #define HA_ISGID     0x0400
  71. #define HA_ISUID     0x0800
  72.  
  73. #define HA_IRUSR     0x0100
  74. #define HA_IWUSR     0x0080 
  75. #define HA_IXUSR     0x0040
  76.  
  77. #define HA_IRGRP     0x0020
  78. #define HA_IWGRP     0x0010
  79. #define HA_IXGRP     0x0008
  80.  
  81. #define HA_IROTH     0x0004
  82. #define HA_IWOTH     0x0002
  83. #define HA_IXOTH     0x0001
  84.  
  85. #define HA_IFMT      0xf000
  86. #define HA_IFIFO     0x1000
  87. #define HA_IFCHR     0x2000
  88. #define HA_IFDIR     0x4000
  89. #define HA_IFBLK     0x6000
  90. #define HA_IFREG     0x8000
  91. #define HA_IFLNK     0xa000
  92. #define HA_IFSOCK    0xc000
  93.  
  94. #define HA_ISDIR(m)  ((m&HA_IFMT)==HA_IFDIR)
  95. #define HA_ISCHR(m)  ((m&HA_IFMT)==HA_IFCHR)
  96. #define HA_ISBLK(m)  ((m&HA_IFMT)==HA_IFBLK)
  97. #define HA_ISLNK(m)  ((m&HA_IFMT)==HA_IFLNK)
  98. #define HA_ISFIFO(m) ((m&HA_IFMT)==HA_IFIFO)
  99. #define HA_ISSOCK(m) ((m&HA_IFMT)==HA_IFSOCK)
  100.  
  101. struct HAPrivate {
  102.   ULONG CRC32;
  103.   UBYTE Method;
  104. };
  105.  
  106. #define HAPI(a)    ((struct HAPrivate *) ((a)->xfi_PrivateInfo))
  107. #define HASCANSIZE    2048
  108.  
  109. static const STRPTR hatypes[] = {"CPY", "ASC", "HSC"};
  110.  
  111. /*
  112.   archive header (intel storage):
  113.   UBYTE[2]    ID = 'HA'
  114.   UWORD        number of entries
  115.  
  116.   file header:
  117.   UBYTE        (version<<4) + compression type
  118.   ULONG        Compressed file size
  119.   ULONG        Original file size
  120.   ULONG        CRC32
  121.   ULONG        timestamp (unix)
  122.   UBYTE[..]    pathname, filename
  123.   UBYTE        Length of machine specific information
  124.   UBYTE[..]    Machine specific information
  125. */
  126.  
  127. ASM(BOOL) HA_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *data),
  128. REG(a6, struct xadMasterBase *xadMasterBase))
  129. { CPUCHECK
  130.   if(data[0] == 'H' && data[1] == 'A' && (data[4]>>4) == 2 &&
  131.   (data[4]&0xF) <= HATYPE_SPECIAL && EndGetI32(data+5) <= 
  132.   EndGetI32(data+9))
  133.     return 1;
  134.   return 0;
  135. }
  136.  
  137. ASM(LONG) HA_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  138. REG(a6, struct xadMasterBase *xadMasterBase))
  139. {
  140.   LONG err, s, i, nsize, psize, msize;
  141.   struct xadFileInfo *fi;
  142.   STRPTR hdr, machine;
  143.  
  144.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, 4, 0, ai)))
  145.   {
  146.     if((hdr = xadAllocVec(HASCANSIZE, MEMF_PUBLIC)))
  147.     {
  148.       while(ai->xai_InPos < ai->xai_InSize && !err)
  149.       {
  150.         if((s = ai->xai_InSize - ai->xai_InPos) > HASCANSIZE)
  151.           s = HASCANSIZE;
  152.         if(!(err = xadHookAccess(XADAC_READ, s, hdr, ai)))
  153.         {
  154.           msize = 0;
  155.           for(psize = 0; psize <= s-20 && hdr[17+psize]; ++psize)
  156.             ;
  157.           for(nsize = 0; nsize+psize <= s-20 && hdr[17+psize+1+nsize]; ++nsize)
  158.             ;
  159.           if(nsize+psize <= s-20)
  160.             msize = hdr[17+psize+1+nsize+1];
  161.       if(hdr[0] >> 4 == 2 && (hdr[0]&0xF) <= HATYPE_SPECIAL &&
  162.       EndGetI32(hdr+1) <= EndGetI32(hdr+5) && psize + nsize + msize <= s-20)
  163.       {
  164.         machine = hdr+20+psize+nsize;
  165.  
  166.         if((hdr[0]&0xF) == HATYPE_SPECIAL)
  167.         {
  168.           if(machine[0] == HAMTYPE_UNIX)
  169.           {
  170.             if(machine[2]>>4 == 0xA) /* check for link */
  171.             {
  172.               if((fi = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1+EndGetI32(hdr+1)+1, TAG_DONE)))
  173.               {
  174.                 i = 0;
  175.                 if(psize)
  176.                 {
  177.               for(i = 0; i < psize; ++i)
  178.               {
  179.                 fi->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  180.                   }
  181.                   if(fi->xfi_FileName[i-1] != '/')
  182.                     fi->xfi_FileName[i++] = '/';
  183.                 }
  184.                 xadCopyMem(hdr+17+psize+1, fi->xfi_FileName+i, nsize+1); i += nsize+1;
  185.  
  186.                 if(!(err = xadHookAccess(XADAC_INPUTSEEK, 20+nsize+psize+msize-s, 0, ai)))
  187.                 {
  188.                   fi->xfi_LinkName = fi->xfi_FileName+i;
  189.                   err = xadHookAccess(XADAC_READ, EndGetI32(hdr+1), fi->xfi_LinkName, ai);
  190.               for(i = 0; fi->xfi_LinkName[i]; ++i)
  191.               {
  192.                 if(fi->xfi_LinkName[i] == 0xFF)
  193.                   fi->xfi_LinkName[i] = '/';
  194.               }
  195.                 }
  196.  
  197.                     xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1), XAD_GETPROTFILEINFO, fi, TAG_DONE);
  198.  
  199.                 fi->xfi_Flags |= XADFIF_LINK|XADFIF_EXTRACTONBUILD;
  200.                     xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
  201.  
  202.                     i = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos, TAG_DONE);
  203.                     if(!err && i)
  204.                       err = i;
  205.               }
  206.               else
  207.                 err = XADERR_NOMEMORY;
  208.             }
  209.             else if(machine[2]>>4 == 0x1) /* fifo */
  210.             {
  211.               if((fi = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1, TAG_DONE)))
  212.               {
  213.                 i = 0;
  214.                 if(psize)
  215.                 {
  216.               for(i = 0; i < psize; ++i)
  217.               {
  218.                 fi->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  219.                   }
  220.                   if(fi->xfi_FileName[i-1] != '/')
  221.                     fi->xfi_FileName[i++] = '/';
  222.                 }
  223.                 xadCopyMem(hdr+17+psize+1, fi->xfi_FileName+i, nsize+1);
  224.                 fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
  225.                 fi->xfi_FileType = XADFILETYPE_UNIXFIFO;
  226.                     xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1), XAD_GETPROTFILEINFO, fi, TAG_DONE);
  227.                     xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
  228.  
  229.                     err = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos-s+20+nsize+psize+msize, TAG_DONE);
  230.               }
  231.             }
  232.             else if((machine[2]>>4) == 0x2 || (machine[2]>>4) == 0x6)
  233.             {
  234.               if((fi = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1, TAG_DONE)))
  235.               {
  236.                 i = 0;
  237.                 if(psize)
  238.                 {
  239.               for(i = 0; i < psize; ++i)
  240.               {
  241.                 fi->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  242.                   }
  243.                   if(fi->xfi_FileName[i-1] != '/')
  244.                     fi->xfi_FileName[i++] = '/';
  245.                 }
  246.                 xadCopyMem(hdr+17+psize+1, fi->xfi_FileName+i, nsize+1);
  247.                 fi->xfi_Flags |= XADFIF_EXTRACTONBUILD;
  248.                 fi->xfi_FileType = (machine[2]>>4) == 0x6 ? XADFILETYPE_UNIXBLOCKDEVICE : XADFILETYPE_UNIXCHARDEVICE;
  249.                     xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1), XAD_GETPROTFILEINFO, fi, TAG_DONE);
  250.                     xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
  251.  
  252.             i = EndGetI32(hdr+1);
  253.             /* set the block-special types here ??? */
  254.  
  255.                     err = xadAddFileEntry(fi, ai, XAD_SETINPOS, ai->xai_InPos-s+20+nsize+psize+msize+i, TAG_DONE);
  256.               }
  257.             }
  258.             else
  259.             {
  260.               err = xadHookAccess(XADAC_INPUTSEEK, 20+nsize+psize+msize+EndGetI32(hdr+1)-s, 0, ai);
  261.             }
  262.           }
  263.           else
  264.             err = xadHookAccess(XADAC_INPUTSEEK, 20+nsize+psize+msize+EndGetI32(hdr+1)-s, 0, ai);
  265.         }
  266.         else if((fi = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1,
  267.         XAD_OBJPRIVINFOSIZE, sizeof(struct HAPrivate), TAG_DONE)))
  268.         {
  269.           i = 0;
  270.           if(psize)
  271.           {
  272.         for(i = 0; i < psize; ++i)
  273.         {
  274.           fi->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  275.             }
  276.             if(fi->xfi_FileName[i-1] != '/')
  277.               fi->xfi_FileName[i++] = '/';
  278.           }
  279.           xadCopyMem(hdr+17+psize+1, fi->xfi_FileName+i, nsize+1);
  280.  
  281.               fi->xfi_CrunchSize = EndGetI32(hdr+1);
  282.               fi->xfi_Size = EndGetI32(hdr+5);
  283.  
  284.           switch(machine[0])
  285.           {
  286.           case HAMTYPE_MSDOS: xadConvertProtection(XAD_PROTMSDOS, machine[1],
  287.             XAD_GETPROTAMIGA, &fi->xfi_Protection, TAG_DONE); break;
  288.           case HAMTYPE_UNIX: xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1),
  289.             XAD_GETPROTAMIGA, &fi->xfi_Protection, TAG_DONE);
  290.             break;
  291.           }
  292.  
  293.           fi->xfi_Flags |= XADFIF_SEEKDATAPOS|XADFIF_EXTRACTONBUILD;
  294.           fi->xfi_DataPos = ai->xai_InPos-s+20+nsize+psize+msize;
  295.  
  296.               xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi->xfi_Date, TAG_DONE);
  297.  
  298.           HAPI(fi)->CRC32 = EndGetI32(hdr+9);
  299.           HAPI(fi)->Method = hdr[0]&15;
  300.           if(HAPI(fi)->Method == HATYPE_DIR)
  301.             fi->xfi_Flags |= XADFIF_DIRECTORY;
  302.           else if(HAPI(fi)->Method <= HATYPE_HSC)
  303.             fi->xfi_EntryInfo = hatypes[HAPI(fi)->Method];
  304.               err = xadAddFileEntry(fi, ai, XAD_SETINPOS, fi->xfi_DataPos+fi->xfi_CrunchSize, TAG_DONE);
  305.         }
  306.         else
  307.           err = XADERR_NOMEMORY;
  308.       }
  309.       else
  310.         err = XADERR_ILLEGALDATA;
  311.     }
  312.       }
  313.       xadFreeObjectA(hdr,0);
  314.     }
  315.     else
  316.       err = XADERR_NOMEMORY;
  317.  
  318.     if(!err && ai->xai_InPos < ai->xai_InSize)
  319.       err = XADERR_ILLEGALDATA;
  320.     if(err)
  321.     {
  322.       ai->xai_Flags |= XADAIF_FILECORRUPT;
  323.       ai->xai_LastError = err;
  324.     }
  325.   }
  326.   return (ai->xai_FileInfo ? 0 : err);
  327. }
  328.  
  329.  
  330. /* Arithmetic Decoding *******************************************************/
  331.  
  332. struct HaArithData {
  333.  struct xadInOut *io;
  334.  UWORD h;
  335.  UWORD l;
  336.  UWORD v;
  337.  WORD  s;
  338.  WORD  gpat;
  339.  WORD  ppat;
  340. };
  341.  
  342. static void HA_ac_init_decode(struct HaArithData *dat)
  343. {
  344.   dat->h = 0xffff;
  345. /*  dat->l = 0; */
  346. /*  dat->gpat = 0; */
  347.   dat->v = xadIOGetChar(dat->io)<<8;
  348.   dat->v |= 0xff&xadIOGetChar(dat->io);
  349. }
  350.  
  351. UWORD HA_ac_threshold_val(struct HaArithData *dat, UWORD tot)
  352. {
  353.   ULONG r;
  354.     
  355.   r = (ULONG)(dat->h - dat->l)+1;
  356.   return (UWORD)((((ULONG)(dat->v-dat->l)+1)*tot-1)/r);
  357. }
  358.  
  359. #define HA_getbit(b)     { dat->gpat <<= 1;                \
  360.               if(!(dat->gpat&0xff)) {            \
  361.                 dat->gpat=xadIOGetChar(dat->io);        \
  362.                 if(dat->gpat&0x100) dat->gpat=0x100;    \
  363.                 else {                    \
  364.                     dat->gpat <<= 1;        \
  365.                     dat->gpat |= 1;            \
  366.                 }                    \
  367.               }                        \
  368.               b |= (dat->gpat&0x100)>>8;            \
  369.             }
  370.  
  371. static void HA_ac_in(struct HaArithData *dat, UWORD low, UWORD high, UWORD tot)
  372. {
  373.   ULONG r;
  374.  
  375.   r = (ULONG)(dat->h - dat->l)+1;
  376.   dat->h = (UWORD)(r*high/tot-1)+dat->l;
  377.   dat->l += (UWORD)(r*low/tot);
  378.   while(!((dat->h^dat->l)&0x8000))
  379.   {
  380.     dat->l <<= 1;
  381.     dat->h <<= 1;
  382.     dat->h |= 1;
  383.     dat->v <<= 1;
  384.     HA_getbit(dat->v);
  385.   }
  386.   while((dat->l&0x4000)&&!(dat->h&0x4000))
  387.   {
  388.     dat->l <<= 1;
  389.     dat->l &= 0x7fff;
  390.     dat->h <<= 1;
  391.     dat->h |= 0x8001;
  392.     dat->v <<= 1;
  393.     dat->v ^= 0x8000;
  394.     HA_getbit(dat->v);
  395.   }
  396. }
  397.  
  398. /* ASC ***********************************************************************/
  399.  
  400. #define HA_POSCODES    31200
  401. #define HA_CTCODES    256
  402. #define HA_PTCODES    16
  403. #define HA_SLCODES    16
  404. #define HA_LLCODES    48
  405. #define HA_TTORD    4
  406. #define HA_LTSTEP    8
  407. #define HA_CTSTEP    1
  408. #define HA_TTSTEP    40
  409. #define HA_PTSTEP    24
  410. #define HA_MAXPT    (250*HA_PTSTEP)
  411. #define HA_MAXLT    (750*HA_LTSTEP)
  412. #define HA_MAXTT    (150*HA_TTSTEP)
  413. #define HA_MAXCT    (1000*HA_CTSTEP)
  414. #define HA_TTOMASK    (HA_TTORD-1);
  415. #define HA_LPLEN    4
  416. #define HA_CPLEN    8
  417. #define HA_LLLEN    16
  418. #define HA_LLBITS    4
  419. #define HA_CCUTOFF    (3*HA_CTSTEP)
  420. #define HA_LCUTOFF    (3*HA_LTSTEP)
  421. #define HA_LTCODES    (HA_SLCODES+HA_LLCODES)
  422. #define HA_LENCODES    (HA_SLCODES+HA_LLCODES*HA_LLLEN)
  423.  
  424. struct HaAscData {
  425.   struct HaArithData arith;
  426.   UWORD cblen;
  427.   UWORD bbf;
  428.   UWORD ccnt;
  429.   UWORD pmax;
  430.   UWORD npt;
  431.   UWORD ces;
  432.   UWORD les;
  433.   UWORD ttcon;
  434.   UWORD ltab[2*HA_LTCODES];
  435.   UWORD eltab[2*HA_LTCODES];
  436.   UWORD ptab[2*HA_PTCODES];
  437.   UWORD ctab[2*HA_CTCODES];
  438.   UWORD ectab[2*HA_CTCODES];
  439.   UWORD ttab[HA_TTORD][2];
  440.   UBYTE b[HA_POSCODES];
  441. };
  442.  
  443. static void HA_tabinit(UWORD *t, UWORD tl, UWORD ival)
  444. {
  445.   UWORD i,j;
  446.     
  447.   for(i = tl; i < 2*tl; ++i)
  448.     t[i] = ival;
  449.   for(i = tl-1, j = (tl<<1)-2; i; --i, j-=2)
  450.   {
  451.     t[i] = t[j] + t[j+1];
  452.   }
  453. }
  454.  
  455. static void HA_tscale(UWORD *t, UWORD tl)
  456. {
  457.   UWORD i,j;
  458.     
  459.   for(i = (tl<<1)-1; i>=tl; --i)
  460.   {
  461.     if(t[i]>1)
  462.       t[i]>>=1;
  463.   }
  464.   for(i = tl-1, j = (tl<<1)-2; i; --i, j-=2)
  465.   {
  466.     t[i] = t[j] + t[j+1];
  467.   }
  468. }
  469.  
  470. static void HA_ttscale(struct HaAscData *dat, UWORD con)
  471. {
  472.   dat->ttab[con][0]>>=1;
  473.   if(dat->ttab[con][0]==0)
  474.     dat->ttab[con][0]=1;
  475.   dat->ttab[con][1]>>=1;
  476.   if(dat->ttab[con][1]==0)
  477.     dat->ttab[con][1]=1;
  478. }
  479.  
  480. static void HA_tupd(UWORD *t, UWORD tl, UWORD maxt, UWORD step, UWORD p)
  481. {
  482.   WORD i;
  483.     
  484.   for(i = p+tl; i; i>>=1)
  485.     t[i] += step;
  486.   if(t[1] >= maxt)
  487.     HA_tscale(t,tl);
  488. }
  489.  
  490. static void HA_tzero(UWORD *t, UWORD tl, UWORD p)
  491. {
  492.   WORD i, step;
  493.     
  494.   for(i = p+tl, step = t[i]; i; i>>=1)
  495.     t[i] -= step;
  496. }
  497.  
  498. static LONG HA_asc(struct xadInOut *io)
  499. {
  500.   struct xadMasterBase *xadMasterBase = io->xio_xadMasterBase;
  501.   UWORD l,p,tv,i,lt;
  502.   struct HaAscData *dat;
  503.  
  504.   if((dat = (struct HaAscData *) xadAllocVec(sizeof(struct HaAscData), MEMF_PUBLIC|MEMF_CLEAR)))
  505.   {
  506.     dat->arith.io = io;
  507.     dat->cblen = HA_POSCODES;
  508.     dat->ces=HA_CTSTEP;
  509.     dat->les=HA_LTSTEP;
  510. /*    dat->ccnt=0; */
  511. /*    dat->ttcon=0; */
  512.     dat->npt = dat->pmax = 1;
  513.     for(i = 0; i < HA_TTORD; ++i)
  514.       dat->ttab[i][0] = dat->ttab[i][1] = HA_TTSTEP;
  515.     HA_tabinit(dat->ltab, HA_LTCODES,0);
  516.     HA_tabinit(dat->eltab,HA_LTCODES,1);
  517.     HA_tabinit(dat->ctab, HA_CTCODES,0);
  518.     HA_tabinit(dat->ectab,HA_CTCODES,1);
  519.     HA_tabinit(dat->ptab, HA_PTCODES,0);
  520.     HA_tupd(dat->ptab,HA_PTCODES,HA_MAXPT,HA_PTSTEP,0);
  521.  
  522.     HA_ac_init_decode(&dat->arith);
  523.     for(;;)
  524.     {
  525.       tv = HA_ac_threshold_val(&dat->arith, dat->ttab[dat->ttcon][0]+dat->ttab[dat->ttcon][1]+1);
  526.       i = dat->ttab[dat->ttcon][0]+dat->ttab[dat->ttcon][1];
  527.       if(dat->ttab[dat->ttcon][0] > tv)
  528.       {
  529.     HA_ac_in(&dat->arith, 0, dat->ttab[dat->ttcon][0], i+1);
  530.     dat->ttab[dat->ttcon][0] += HA_TTSTEP;
  531.  
  532.     if(i >= HA_MAXTT)
  533.       HA_ttscale(dat, dat->ttcon);
  534.  
  535.     dat->ttcon = (dat->ttcon<<1) & HA_TTOMASK;
  536.     tv = HA_ac_threshold_val(&dat->arith, dat->ctab[1] + dat->ces);
  537.  
  538.     if(tv >= dat->ctab[1])
  539.     {
  540.       HA_ac_in(&dat->arith, dat->ctab[1], dat->ctab[1]+dat->ces, dat->ctab[1]+dat->ces);
  541.       tv = HA_ac_threshold_val(&dat->arith, dat->ectab[1]);
  542.       for(l=2,lt=0;;)
  543.       {
  544.         if(lt+dat->ectab[l]<=tv)
  545.         {
  546.           lt += dat->ectab[l];
  547.           ++l;
  548.         }
  549.         if(l >= HA_CTCODES)
  550.         {
  551.           l -= HA_CTCODES;
  552.           break;
  553.         }
  554.         l <<= 1;
  555.       }
  556.       HA_ac_in(&dat->arith, lt,lt+dat->ectab[HA_CTCODES+l], dat->ectab[1]);
  557.       HA_tzero(dat->ectab, HA_CTCODES, l);
  558.       if(dat->ectab[1] != 0)
  559.         dat->ces += HA_CTSTEP;
  560.       else
  561.         dat->ces = 0;
  562.       for(i = l < HA_CPLEN ? 0 : l-HA_CPLEN; i < (l+HA_CPLEN >= HA_CTCODES-1 ? HA_CTCODES-1:l+HA_CPLEN); ++i)
  563.       {
  564.         if(dat->ectab[HA_CTCODES+i])
  565.           HA_tupd(dat->ectab, HA_CTCODES, HA_MAXCT, 1, i);
  566.       }
  567.     }
  568.     else
  569.     {
  570.       for(l=2,lt=0;;)
  571.       {
  572.         if(lt+dat->ctab[l] <= tv)
  573.         {
  574.           lt += dat->ctab[l];
  575.           l++;
  576.         }
  577.         if(l >= HA_CTCODES)
  578.         {
  579.           l -= HA_CTCODES;
  580.           break;
  581.         }
  582.         l <<= 1;
  583.       }
  584.       HA_ac_in(&dat->arith, lt, lt+dat->ctab[HA_CTCODES+l],dat->ctab[1]+dat->ces);
  585.     }
  586.  
  587.     HA_tupd(dat->ctab, HA_CTCODES, HA_MAXCT, HA_CTSTEP, l);
  588.     if(dat->ctab[HA_CTCODES+l] == HA_CCUTOFF)
  589.       dat->ces -= HA_CTSTEP < dat->ces ? HA_CTSTEP : dat->ces-1; 
  590.  
  591.     dat->b[dat->bbf] = xadIOPutChar(io, l);
  592.         if(++dat->bbf == dat->cblen)
  593.           dat->bbf=0;
  594.  
  595.     if(dat->ccnt < HA_POSCODES)
  596.       ++dat->ccnt;
  597.       }
  598.       else if (i > tv)
  599.       {
  600.     HA_ac_in(&dat->arith, dat->ttab[dat->ttcon][0],i,i+1);
  601.     dat->ttab[dat->ttcon][1] += HA_TTSTEP;
  602.     if(i >= HA_MAXTT)
  603.       HA_ttscale(dat, dat->ttcon);
  604.     dat->ttcon = ((dat->ttcon<<1)|1)&HA_TTOMASK;
  605.     while(dat->ccnt > dat->pmax)
  606.     {
  607.       HA_tupd(dat->ptab, HA_PTCODES, HA_MAXPT, HA_PTSTEP, dat->npt++);
  608.       dat->pmax <<= 1;    
  609.     }
  610.     tv = HA_ac_threshold_val(&dat->arith, dat->ptab[1]);
  611.     for(p=2,lt=0;;)
  612.     {
  613.       if(lt + dat->ptab[p] <= tv)
  614.       {
  615.         lt += dat->ptab[p];
  616.         p++;
  617.       }
  618.       if(p >= HA_PTCODES)
  619.       {
  620.         p -= HA_PTCODES;
  621.         break;
  622.       }
  623.       p <<= 1;
  624.     }
  625.     HA_ac_in(&dat->arith, lt, lt+dat->ptab[HA_PTCODES+p], dat->ptab[1]);
  626.     HA_tupd(dat->ptab, HA_PTCODES, HA_MAXPT, HA_PTSTEP, p);
  627.     if(p > 1)
  628.     {
  629.       for(i=1; p; i <<= 1)
  630.         --p;
  631.       i >>= 1;
  632.       if(i==(dat->pmax>>1))
  633.         l = dat->ccnt-(dat->pmax>>1);
  634.       else
  635.         l=i;
  636.       p = HA_ac_threshold_val(&dat->arith, l);
  637.       HA_ac_in(&dat->arith, p, p+1, l);
  638.       p += i;
  639.     }
  640.     tv = HA_ac_threshold_val(&dat->arith, dat->ltab[1]+dat->les);
  641.     if(tv >= dat->ltab[1])
  642.     {
  643.       HA_ac_in(&dat->arith, dat->ltab[1], dat->ltab[1]+dat->les, dat->ltab[1]+dat->les);
  644.       tv = HA_ac_threshold_val(&dat->arith, dat->eltab[1]);
  645.       for(l=2,lt=0;;)
  646.       {
  647.         if(lt+dat->eltab[l] <= tv)
  648.         {
  649.           lt += dat->eltab[l];
  650.           ++l;
  651.         }
  652.         if(l >= HA_LTCODES)
  653.         {
  654.           l -= HA_LTCODES;
  655.           break;
  656.         }
  657.         l <<= 1;
  658.       }
  659.       HA_ac_in(&dat->arith, lt, lt+dat->eltab[HA_LTCODES+l], dat->eltab[1]);
  660.       HA_tzero(dat->eltab, HA_LTCODES, l);
  661.       if(dat->eltab[1] != 0)
  662.         dat->les += HA_LTSTEP;
  663.       else
  664.         dat->les = 0;
  665.       for(i = l < HA_LPLEN ? 0 : l-HA_LPLEN; i<(l+HA_LPLEN >= HA_LTCODES-1 ? HA_LTCODES-1:l+HA_LPLEN);++i)
  666.       {
  667.         if(dat->eltab[HA_LTCODES+i])
  668.           HA_tupd(dat->eltab,HA_LTCODES,HA_MAXLT,1,i);
  669.       }
  670.     }
  671.     else
  672.     {
  673.       for(l=2,lt=0;;)
  674.       {
  675.         if(lt+dat->ltab[l] <= tv)
  676.         {
  677.           lt += dat->ltab[l];
  678.           ++l;
  679.         }
  680.         if(l >= HA_LTCODES)
  681.         {
  682.           l -= HA_LTCODES;
  683.           break;
  684.         }
  685.         l <<= 1;
  686.       }
  687.       HA_ac_in(&dat->arith, lt, lt+dat->ltab[HA_LTCODES+l], dat->ltab[1]+dat->les);
  688.     }
  689.     HA_tupd(dat->ltab, HA_LTCODES, HA_MAXLT, HA_LTSTEP, l);
  690.     if(dat->ltab[HA_LTCODES+l] == HA_LCUTOFF)
  691.       dat->les -= HA_LTSTEP < dat->les ? HA_LTSTEP : dat->les-1; 
  692.     if(l == HA_SLCODES-1)
  693.       l = HA_LENCODES-1;
  694.     else if(l >= HA_SLCODES)
  695.     {
  696.       i = HA_ac_threshold_val(&dat->arith, HA_LLLEN);
  697.       HA_ac_in(&dat->arith, i, i+1, HA_LLLEN);
  698.       l = ((l-HA_SLCODES) << HA_LLBITS)+i+HA_SLCODES-1;
  699.     }
  700.     l += 3;
  701.     if(dat->ccnt < HA_POSCODES)
  702.     {
  703.       dat->ccnt += l;
  704.       if(dat->ccnt > HA_POSCODES)
  705.         dat->ccnt = HA_POSCODES;
  706.     }
  707.         if(dat->bbf > p)
  708.           p = dat->bbf-1-p;
  709.         else
  710.           p=dat->cblen-1-p+dat->bbf;
  711.         while (l--)
  712.         {
  713.       dat->b[dat->bbf] = xadIOPutChar(io, dat->b[p]);
  714.       if(++dat->bbf == dat->cblen)
  715.         dat->bbf=0;
  716.       if(++p == dat->cblen)
  717.         p=0;
  718.         }
  719.       }
  720.       else
  721.       {
  722.     HA_ac_in(&dat->arith, i, i+1, i+1);
  723.         break;
  724.       }
  725.     }
  726.  
  727.     xadFreeObjectA(dat, 0);
  728.   }
  729.   return io->xio_Error;
  730. }
  731.  
  732. /* HSC ***********************************************************************/
  733.  
  734. #define HA_IECLIM    32    /* initial escape counter upper limit */
  735. #define HA_NECLIM    5    /* no escape expected counter limit */
  736. #define HA_NECTLIM    4
  737. #define HA_NECMAX    10    /* no escape expected counter maximum */
  738. #define HA_MAXCLEN    4    /* assumed to be 4 in several places */
  739. #define HA_NUMCON    10000    /* number of contexts to remember */ 
  740. #define HA_NUMCFB    32760    /* number of frequencies to remember */
  741. #define HA_ESCTH    3    /* threshold for escape calculation */
  742. #define HA_MAXTVAL    8000    /* maximum frequency value */
  743. #define HA_RFMINI    4    /* initial refresh counter value */
  744. #define HA_HTLEN    16384    /* length of hash table */
  745. #define HA_NIL        0xffff    /* NIL pointer in lists */
  746. #define HA_ESC        256    /* escape symbol */
  747.  
  748. struct HaHscData {
  749.   struct HaArithData arith;
  750.   UWORD usp;            /* stack pointer */
  751.   WORD  cslen;            /* length of context to search */
  752.   WORD  cmsp;            /* pointer to cmstack */
  753.   WORD  dropcnt;        /* counter for context len drop */
  754.   UWORD nrel;            /* context for frequency block release */
  755.   UWORD elf;            /* first of expire list */
  756.   UWORD    ell;            /* last of expire list */
  757.   UWORD fcfbl;            /* pointer to free frequency blocks */
  758.   UWORD elp[HA_NUMCON];        /* expire list previous pointer array */
  759.   UWORD eln[HA_NUMCON];        /* expire list next pointer array */
  760.   UWORD hrt[HA_HTLEN];        /* semi random data for hashing */
  761.   UWORD hs[HA_MAXCLEN+1];    /* hash stack for context search */ 
  762.   UWORD hp[HA_NUMCON];        /* hash list pointer array */
  763.   UWORD as[HA_MAXCLEN+1];    /* indexes to frequency array */
  764.   UWORD cps[HA_MAXCLEN+1];    /* context pointers */
  765.   UWORD nb[HA_NUMCFB];        /* next pointer for frequency array */
  766.   UWORD fa[HA_NUMCFB];        /* frequency array */
  767.   UWORD ft[HA_NUMCON];        /* total frequency of context */
  768.   UWORD ht[HA_HTLEN];        /* hash table */
  769.   UBYTE nec;            /* counter for no escape expected */
  770.   UBYTE maxclen;        /* current maximum length for context */ 
  771.   UBYTE curcon[4];        /* current context */
  772.   UBYTE cmask[256];        /* masked characters */
  773.   UBYTE cmstack[256];        /* stack of cmask[] entries to clear */ 
  774.   UBYTE cl[HA_NUMCON];        /* context length array */
  775.   UBYTE con[HA_NUMCON][4];    /* context array */
  776.   UBYTE fe[HA_NUMCON];        /* frequencys under ESCTH in context */
  777.   UBYTE fc[HA_NUMCFB];        /* character for frequency array */
  778.   UBYTE cc[HA_NUMCON];        /* character counts */
  779.   UBYTE rfm[HA_NUMCON];        /* refresh counter array */
  780.   UBYTE iec[HA_MAXCLEN+1];    /* initial escape counters */
  781. };
  782.  
  783. static UWORD HA_find_next(struct HaHscData *dat)
  784. {
  785.   WORD i,k;
  786.   UWORD cp;
  787.     
  788.   for(i = dat->cslen-1; i >= 0; --i)
  789.   {
  790.     k = dat->hs[i];
  791.     for(cp = dat->ht[k]; cp != HA_NIL; cp = dat->hp[cp])
  792.     {
  793.       if(dat->cl[cp] == i)
  794.       {
  795.     switch(i)
  796.     {
  797.     case 4: if(dat->curcon[3] != dat->con[cp][3]) break;
  798.         case 3: if(dat->curcon[2] != dat->con[cp][2]) break;
  799.         case 2: if(dat->curcon[1] != dat->con[cp][1]) break;
  800.         case 1: if(dat->curcon[0] != dat->con[cp][0]) break;
  801.         case 0: dat->cslen = i; return cp;
  802.     }
  803.       }    
  804.     }
  805.   }
  806.  
  807.   return HA_NIL;
  808. }
  809.  
  810. static UWORD HA_find_longest(struct HaHscData *dat)
  811. {
  812.   dat->hs[1] = dat->hrt[dat->curcon[0]];
  813.   dat->hs[2] = dat->hrt[(dat->curcon[1]+dat->hs[1])&(HA_HTLEN-1)];
  814.   dat->hs[3] = dat->hrt[(dat->curcon[2]+dat->hs[2])&(HA_HTLEN-1)];
  815.   dat->hs[4] = dat->hrt[(dat->curcon[3]+dat->hs[3])&(HA_HTLEN-1)];
  816.   dat->usp = 0;
  817.   while(dat->cmsp)
  818.     dat->cmask[dat->cmstack[--dat->cmsp]] = 0;
  819.   dat->cslen = HA_MAXCLEN+1;
  820.  
  821.   return HA_find_next(dat);
  822. }
  823.  
  824. static UWORD HA_adj_escape_prob(struct HaHscData *dat, UWORD esc, UWORD cp)
  825. {
  826.   if(dat->ft[cp] == 1)
  827.     return (UWORD) (dat->iec[dat->cl[cp]] >= (HA_IECLIM >> 1) ? 2 : 1);
  828.   if(dat->cc[cp] == 255)
  829.     return 1;
  830.   if(dat->cc[cp] && ((dat->cc[cp]+1) << 1) >= dat->ft[cp])
  831.   {
  832.     esc = (WORD)((LONG)esc*((dat->cc[cp]+1) << 1) / dat->ft[cp]);
  833.     if(dat->cc[cp] + 1 == dat->ft[cp])
  834.       esc += (dat->cc[cp]+1)>>1;
  835.   }
  836.   return (UWORD) (esc?esc:1);
  837. }
  838.  
  839. static WORD HA_decode_first(struct HaHscData *dat, UWORD cp)
  840. {
  841.   UWORD c, tv, i;
  842.   WORD sum,tot,esc,cf = 0;
  843.   UBYTE sv;
  844.  
  845.   esc = HA_adj_escape_prob(dat, dat->fe[cp], cp);
  846.   tot = dat->ft[cp];
  847.   if(dat->nec >= HA_NECLIM)
  848.   {
  849.     if(tot <= HA_NECTLIM && dat->nec == HA_NECMAX)
  850.       sv=2;
  851.     else
  852.       sv=1;
  853.     tot <<= sv;
  854.     tv = HA_ac_threshold_val(&dat->arith, tot+esc) >> sv;
  855.     for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  856.     {
  857.       if(sum+dat->fa[c] <= tv)
  858.         sum += dat->fa[c];
  859.       else
  860.       {
  861.     cf = dat->fa[c] << sv;
  862.     break;
  863.       }
  864.     }
  865.     sum <<= sv;
  866.   }
  867.   else
  868.   {
  869.     tv = HA_ac_threshold_val(&dat->arith, tot+esc);
  870.     for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  871.     {
  872.       if(sum+dat->fa[c] <= tv)
  873.         sum += dat->fa[c];
  874.       else
  875.       {
  876.     cf = dat->fa[c];
  877.     break;
  878.       }
  879.     }
  880.   }
  881.   dat->usp = 1;
  882.   if(c != HA_NIL)
  883.   {
  884.     HA_ac_in(&dat->arith, sum, sum+cf, tot+esc);
  885.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]])
  886.       --dat->iec[dat->cl[cp]];
  887.     dat->as[0] = c;
  888.     dat->cps[0] = cp;
  889.     c = dat->fc[c];
  890.     if(dat->nec < HA_NECMAX)
  891.       ++dat->nec;
  892.   }
  893.   else
  894.   {
  895.     HA_ac_in(&dat->arith, tot,tot+esc,tot+esc);
  896.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]] < HA_IECLIM)
  897.       ++dat->iec[dat->cl[cp]];
  898.     for(i = cp; i != HA_NIL; sum=i,i=dat->nb[i])
  899.     {
  900.       dat->cmstack[dat->cmsp++] = dat->fc[i];
  901.       dat->cmask[dat->fc[i]]=1;
  902.     }
  903.     dat->cps[0]=0x8000|cp;
  904.     dat->as[0]=sum;
  905.     c = HA_ESC;
  906.     dat->nec = 0;
  907.   }
  908.   return (WORD) c;
  909. }
  910.  
  911. static WORD HA_decode_rest(struct HaHscData *dat, UWORD cp)
  912. {
  913.   UWORD c, tv, i;
  914.   WORD sum,tot,esc,cf = 0;
  915.     
  916.   esc=tot=0;
  917.   for(i = cp; i != HA_NIL; i=dat->nb[i])
  918.   {
  919.     if(!dat->cmask[dat->fc[i]])
  920.     {
  921.       tot += dat->fa[i];
  922.       if(dat->fa[i] < HA_ESCTH)
  923.         ++esc;
  924.     }
  925.   }
  926.   esc = HA_adj_escape_prob(dat, esc, cp);
  927.   tv = HA_ac_threshold_val(&dat->arith, tot+esc);
  928.   for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  929.   {
  930.     if(!dat->cmask[dat->fc[c]])
  931.     {
  932.       if(sum+dat->fa[c] <= tv)
  933.         sum += dat->fa[c];
  934.       else
  935.       {
  936.     cf = dat->fa[c];
  937.     break;
  938.       }
  939.     }
  940.   }
  941.   if(c != HA_NIL)
  942.   {
  943.     HA_ac_in(&dat->arith, sum,sum+cf,tot+esc);
  944.     if(dat->ft[cp]==1 && dat->iec[dat->cl[cp]])
  945.       --dat->iec[dat->cl[cp]];
  946.     dat->as[dat->usp] = c;
  947.     dat->cps[dat->usp++] = cp;
  948.     c = dat->fc[c];
  949.     ++dat->nec;
  950.   }
  951.   else
  952.   {
  953.     HA_ac_in(&dat->arith, tot,tot+esc,tot+esc);
  954.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]] < HA_IECLIM)
  955.       ++dat->iec[dat->cl[cp]];
  956.     for(i = cp; i != HA_NIL; sum=i,i=dat->nb[i])
  957.     {
  958.       if(!dat->cmask[dat->fc[i]])
  959.       {
  960.     dat->cmstack[dat->cmsp++] = dat->fc[i];
  961.     dat->cmask[dat->fc[i]] = 1;
  962.       }
  963.     }
  964.     dat->cps[dat->usp] = 0x8000|cp;
  965.     dat->as[dat->usp++]=sum;        /* sum holds last i !! */
  966.     c = HA_ESC;
  967.   }
  968.  
  969.   return (WORD) c;
  970. }
  971.  
  972. static WORD HA_decode_new(struct HaHscData *dat)
  973. {
  974.   WORD c;
  975.   UWORD tv,sum,tot;
  976.     
  977.   tot = 257 - dat->cmsp;
  978.   tv = HA_ac_threshold_val(&dat->arith, tot);
  979.   for(c = sum = 0; c < 256; ++c)
  980.   {
  981.     if(dat->cmask[c])
  982.       continue;
  983.     if(sum+1 <= tv)
  984.       ++sum;
  985.     else
  986.       break;
  987.   }
  988.   HA_ac_in(&dat->arith, sum, sum+1, tot);    
  989.   return c;
  990. }
  991.  
  992. static void HA_el_movefront(struct HaHscData *dat, UWORD cp)
  993. {
  994.   if(cp == dat->elf)
  995.     return;
  996.   if(cp == dat->ell)
  997.     dat->ell = dat->elp[cp];
  998.   else
  999.   {
  1000.     dat->elp[dat->eln[cp]] = dat->elp[cp];
  1001.     dat->eln[dat->elp[cp]] = dat->eln[cp];
  1002.   }    
  1003.   dat->elp[dat->elf] = cp;
  1004.   dat->eln[cp] = dat->elf;
  1005.   dat->elf = cp;
  1006. }
  1007.  
  1008. static void HA_release_cfblocks(struct HaHscData *dat)
  1009. {
  1010.   UWORD i,j,d;
  1011.     
  1012.   do
  1013.   {
  1014.     do
  1015.     {
  1016.       if(++dat->nrel == HA_NUMCON)
  1017.         dat->nrel = 0;
  1018.     } while(dat->nb[dat->nrel] == HA_NIL);
  1019.     for(i=0; i <= dat->usp; ++i)
  1020.       if((dat->cps[i]&0x7fff) == dat->nrel)
  1021.         break;
  1022.   } while(i <= dat->usp);
  1023.  
  1024.   for(i = dat->nb[dat->nrel], d = dat->fa[dat->nrel]; i != HA_NIL; i = dat->nb[i])
  1025.     if(dat->fa[i] < d)
  1026.       d = dat->fa[i];
  1027.   ++d;
  1028.   if(dat->fa[dat->nrel] < d)
  1029.   {
  1030.     for(i = dat->nb[dat->nrel]; dat->fa[i] < d && dat->nb[i] != HA_NIL; i = dat->nb[i])
  1031.       ;
  1032.     dat->fa[dat->nrel] = dat->fa[i];
  1033.     dat->fc[dat->nrel] = dat->fc[i];
  1034.     j = dat->nb[i];
  1035.     dat->nb[i] = dat->fcfbl;
  1036.     dat->fcfbl = dat->nb[dat->nrel];
  1037.     if((dat->nb[dat->nrel] = j) == HA_NIL)
  1038.     {
  1039.       dat->cc[dat->nrel] = 0;
  1040.       dat->fe[dat->nrel] = (dat->ft[dat->nrel] = dat->fa[dat->nrel]) < HA_ESCTH ? 1 : 0;
  1041.       return;
  1042.     }
  1043.   }
  1044.   dat->fe[dat->nrel] = (dat->ft[dat->nrel] = dat->fa[dat->nrel] /= d) < HA_ESCTH ? 1 : 0;
  1045.   dat->cc[dat->nrel] = 0;
  1046.   for(j = dat->nrel, i = dat->nb[j]; i != HA_NIL;)
  1047.   {
  1048.     if(dat->fa[i] < d)
  1049.     {
  1050.       dat->nb[j] = dat->nb[i];
  1051.       dat->nb[i] = dat->fcfbl;
  1052.       dat->fcfbl = i;
  1053.       i = dat->nb[j];
  1054.     }
  1055.     else
  1056.     {
  1057.        ++dat->cc[dat->nrel];
  1058.        dat->ft[dat->nrel] += dat->fa[i] /= d;
  1059.        if(dat->fa[i] < HA_ESCTH)
  1060.          dat->fe[dat->nrel]++;
  1061.        j=i;
  1062.        i = dat->nb[i];
  1063.     }
  1064.   }
  1065. }
  1066.  
  1067. static void HA_add_model(struct HaHscData *dat, WORD c)
  1068. {
  1069.   UWORD i;
  1070.   WORD cp;
  1071.     
  1072.   while(dat->usp != 0)
  1073.   {
  1074.     i = dat->as[--dat->usp];
  1075.     cp = dat->cps[dat->usp];
  1076.     if(cp&0x8000)
  1077.     {
  1078.       cp &= 0x7fff;
  1079.       if(dat->fcfbl == HA_NIL)
  1080.         HA_release_cfblocks(dat);
  1081.       dat->nb[i] = dat->fcfbl;
  1082.       i = dat->nb[i];
  1083.       dat->fcfbl = dat->nb[dat->fcfbl];
  1084.       dat->nb[i] = HA_NIL;
  1085.       dat->fa[i] = 1;
  1086.       dat->fc[i] = c;
  1087.       ++dat->cc[cp];
  1088.       ++dat->fe[cp];
  1089.     }
  1090.     else if(++dat->fa[i] == HA_ESCTH)
  1091.       --dat->fe[cp];
  1092.     if((dat->fa[i]<<1) < ++dat->ft[cp] / (dat->cc[cp]+1))
  1093.       --dat->rfm[cp];
  1094.     else if(dat->rfm[cp] < HA_RFMINI)
  1095.       ++dat->rfm[cp];
  1096.     if(!dat->rfm[cp] || dat->ft[cp] >= HA_MAXTVAL)
  1097.     {
  1098.       ++dat->rfm[cp];
  1099.       dat->fe[cp] = dat->ft[cp]=0;
  1100.       for(i = cp; i != HA_NIL; i = dat->nb[i])
  1101.       {
  1102.     if(dat->fa[i] > 1)
  1103.     {
  1104.       dat->ft[cp] += dat->fa[i] >>= 1;
  1105.       if(dat->fa[i] < HA_ESCTH)
  1106.         ++dat->fe[cp];
  1107.     }
  1108.     else
  1109.     {
  1110.       ++dat->ft[cp];
  1111.       ++dat->fe[cp];
  1112.     }
  1113.       }
  1114.     }
  1115.   }
  1116. }
  1117.  
  1118. #define HA_HASH(s,l,h)    { h = 0; if (l) h=dat->hrt[s[0]];             \
  1119.               if (l>1) h=dat->hrt[(s[1]+h)&(HA_HTLEN-1)]; \
  1120.               if (l>2) h=dat->hrt[(s[2]+h)&(HA_HTLEN-1)]; \
  1121.               if (l>3) h=dat->hrt[(s[3]+h)&(HA_HTLEN-1)];}
  1122.  
  1123. static UWORD HA_make_context(struct HaHscData *dat, UBYTE conlen, WORD c)
  1124. {
  1125.   WORD i;
  1126.   UWORD nc,fp;
  1127.     
  1128.   nc = dat->ell;
  1129.   dat->ell = dat->elp[nc];
  1130.   dat->elp[dat->elf] = nc;
  1131.   dat->eln[nc] = dat->elf;
  1132.   dat->elf = nc;
  1133.   if(dat->cl[nc] != 0xff)
  1134.   {
  1135.     if(dat->cl[nc] == HA_MAXCLEN && --dat->dropcnt==0)
  1136.       dat->maxclen = HA_MAXCLEN-1;
  1137.     HA_HASH(dat->con[nc], dat->cl[nc], i);
  1138.     if(dat->ht[i] == nc)
  1139.       dat->ht[i] = dat->hp[nc];
  1140.     else
  1141.     {
  1142.       for(i = dat->ht[i]; dat->hp[i] != nc; i = dat->hp[i])
  1143.         ;
  1144.       dat->hp[i] = dat->hp[nc];
  1145.     }
  1146.     if(dat->nb[nc] != HA_NIL)
  1147.     {
  1148.       for(fp = dat->nb[nc]; dat->nb[fp] != HA_NIL; fp = dat->nb[fp])
  1149.         ;
  1150.       dat->nb[fp] = dat->fcfbl;
  1151.       dat->fcfbl = dat->nb[nc];
  1152.     }
  1153.   }
  1154.   dat->nb[nc] = HA_NIL;
  1155.   dat->fe[nc] = dat->ft[nc] = dat->fa[nc] = 1;
  1156.   dat->fc[nc] = c;
  1157.   dat->rfm[nc] = HA_RFMINI;
  1158.   dat->cc[nc] = 0;
  1159.   dat->cl[nc] = conlen;
  1160.   dat->con[nc][0] = dat->curcon[0];
  1161.   dat->con[nc][1] = dat->curcon[1];
  1162.   dat->con[nc][2] = dat->curcon[2];
  1163.   dat->con[nc][3] = dat->curcon[3];
  1164.   HA_HASH(dat->curcon, conlen, i);
  1165.   dat->hp[nc] = dat->ht[i];
  1166.   dat->ht[i] = nc;
  1167.   return nc;
  1168. }
  1169.  
  1170. static LONG HA_hsc(struct xadInOut *io)
  1171. {
  1172.   struct xadMasterBase *xadMasterBase = io->xio_xadMasterBase;
  1173.   struct HaHscData *dat;
  1174.   WORD c = 0, i;
  1175.   UWORD cp;
  1176.   LONG z,h,l,t;
  1177.   UBYTE ncmax,ncmin;
  1178.  
  1179.   if((dat = (struct HaHscData *) xadAllocVec(sizeof(struct HaHscData), MEMF_PUBLIC|MEMF_CLEAR)))
  1180.   {
  1181.     dat->arith.io = io;
  1182.  
  1183.     dat->maxclen = HA_MAXCLEN;
  1184.     dat->iec[0] = (HA_IECLIM>>1);
  1185.     for(i=1; i <= HA_MAXCLEN; ++i)
  1186.       dat->iec[i] = (HA_IECLIM>>1)-1;
  1187.     dat->dropcnt = HA_NUMCON/4;
  1188. /*    nec=0; */
  1189. /*    nrel=0; */
  1190. /*    dat->hs[0] = 0; */
  1191.     for(i=0; i < HA_HTLEN; ++i)
  1192.       dat->ht[i] = HA_NIL;
  1193.     for(i=0; i < HA_NUMCON; ++i)
  1194.     {
  1195.       dat->eln[i] = i+1;
  1196.       dat->elp[i] = i-1;
  1197.       dat->cl[i] = 0xff;
  1198.       dat->nb[i] = HA_NIL;
  1199.     }
  1200. /*    dat->elf=0; */
  1201.     dat->ell = HA_NUMCON-1;
  1202.     for(i = HA_NUMCON; i < HA_NUMCFB-1; ++i)
  1203.       dat->nb[i] = i+1;
  1204.     dat->nb[i] = HA_NIL;
  1205.     dat->fcfbl = HA_NUMCON;
  1206. /*    dat->curcon[3] = dat->curcon[2] = dat->curcon[1] = dat->curcon[0] = 0; */
  1207. /*    dat->cmsp = 0; */
  1208. /*    for(i=0; i < 256; ++i) */
  1209. /*      dat->cmask[i] = 0; */
  1210.     for(z=10, i=0; i < HA_HTLEN; ++i)
  1211.     {
  1212.       h = z/(2147483647L/16807L);
  1213.       l = z%(2147483647L/16807L);
  1214.       if((t = 16807L*l-(2147483647L%16807L)*h)>0)
  1215.         z=t;
  1216.       else
  1217.         z=t+2147483647L;
  1218.       dat->hrt[i] = z&(HA_HTLEN-1);
  1219.     }
  1220.  
  1221.     HA_ac_init_decode(&dat->arith);
  1222.     while(c != HA_ESC && !(io->xio_Flags & (XADIOF_LASTOUTBYTE|XADIOF_ERROR)))
  1223.     {
  1224.       cp = HA_find_longest(dat);
  1225.       ncmin = cp == HA_NIL ? 0 : dat->cl[cp]+1;
  1226.       ncmax = dat->maxclen+1;
  1227.       for(;;)
  1228.       {
  1229.     if(cp == HA_NIL)
  1230.     {
  1231.           c = HA_decode_new(dat);
  1232.       break;
  1233.         }            
  1234.     if((c = dat->cmsp ? HA_decode_rest(dat, cp) : HA_decode_first(dat, cp)) != HA_ESC)
  1235.     {
  1236.       HA_el_movefront(dat, cp);
  1237.       break;
  1238.         }        
  1239.         cp = HA_find_next(dat);
  1240.       }
  1241.       if(c != HA_ESC)
  1242.       {
  1243.         HA_add_model(dat, c);
  1244.         while(ncmax > ncmin)
  1245.           HA_make_context(dat, --ncmax, c);
  1246.         dat->curcon[3] = dat->curcon[2];
  1247.         dat->curcon[2] = dat->curcon[1];
  1248.     dat->curcon[1] = dat->curcon[0];
  1249.     dat->curcon[0] = c;
  1250.     xadIOPutChar(io, c);
  1251.       }
  1252.     }
  1253.  
  1254.     xadFreeObjectA(dat, 0);
  1255.   }
  1256.   return io->xio_Error;
  1257. }
  1258.  
  1259. /*****************************************************************************/
  1260.  
  1261. ASM(LONG) HA_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  1262. REG(a6, struct xadMasterBase *xadMasterBase))
  1263. {
  1264.   struct xadFileInfo *fi;
  1265.   struct xadInOut *io;
  1266.   LONG err;
  1267.  
  1268.   fi = ai->xai_CurFile;
  1269.  
  1270.   if((io = xadIOAlloc(XADIOF_ALLOCINBUFFER|XADIOF_ALLOCOUTBUFFER|XADIOF_NOCRC16|XADIOF_NOINENDERR, ai, xadMasterBase)))
  1271.   {
  1272.     io->xio_InSize = fi->xfi_CrunchSize;
  1273.     io->xio_OutSize = fi->xfi_Size;
  1274.     io->xio_CRC32 = ~0;
  1275.  
  1276.     switch(HAPI(fi)->Method)
  1277.     {
  1278.     case HATYPE_CPY:
  1279.       while(!(io->xio_Flags & (XADIOF_LASTOUTBYTE|XADIOF_ERROR)))
  1280.         xadIOPutChar(io, xadIOGetChar(io));
  1281.       err = io->xio_Error;
  1282.       break;
  1283.     case HATYPE_ASC: err = HA_asc(io); break;
  1284.     case HATYPE_HSC: err = HA_hsc(io); break;
  1285.     default: err = XADERR_DATAFORMAT;
  1286.     }
  1287.  
  1288.     if(!err)
  1289.       err = xadIOWriteBuf(io);
  1290.     if(!err && ~io->xio_CRC32 != HAPI(fi)->CRC32)
  1291.       err = XADERR_CHECKSUM;
  1292.     xadFreeObjectA(io, 0);
  1293.   }
  1294.   else
  1295.     err = XADERR_NOMEMORY;
  1296.  
  1297.   return err;
  1298. }
  1299.  
  1300. /*****************************************************************************/
  1301.  
  1302. const struct xadClient HA_Client = {
  1303. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, HA_VERSION, HA_REVISION,
  1304. 22, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_HA, "HA",
  1305. (BOOL (*)()) HA_RecogData, (LONG (*)()) HA_GetInfo,
  1306. (LONG (*)()) HA_UnArchive, 0};
  1307.  
  1308. #endif /* XADMASTER_HA_C */
  1309.